import Code from "components/Markdown/Code"

export const meta = {
  title: "Prisma & TypeORM",
  position: 60,
  description: "Learn how Prisma compares to TypeORM"
}

## Reading data

### Fetching single objects

TypeORM

```ts
const userRepository = getRepository(User)
const user = await userRepository.findOne(id)
```

Prisma

```ts
const user = await prisma.user({ id })
```

### Fetching selected scalars of single objects

TypeORM

```ts
const userRepository = getRepository(User) 
const user = await userRepository.findOne(id, {
  select: ["id", "email"]
})
```

Prisma

```ts
const userFragment = await prisma.user({ id }).$fragment(`
  fragment NameAndEmail on User { id email }`
`)
```

### Fetching relations

TypeORM 

<Code languages={["Using `relations`", "Using JOIN", "Eager relations"]}>

```ts
const userRepository = getRepository(User)
const user = await userRepository.findOne(id, {
  relations: ["posts"]
})
```

```ts
const userRepository = getRepository(User)
const user = await userRepository.findOne(id, {
  join: {
    alias: "user",
    leftJoinAndSelect: {
      posts: "user.posts"
    }
  }
})
```

```ts
const userRepository = getRepository(User)
const user = await userRepository.findOne(id)
```

</Code>

Prisma

<Code languages={["Fluent API", "Using fragments", "Native GraphQL"]}>

```ts
const postsByUser = await prisma
  .user({ id })
  .posts()
```

```ts
const userWithPosts = await prisma
  .user({ id })
  .$fragment(`
    fragment UserPosts on User {
      posts { id title content published }
    }
  `)
```

```ts
const userWithPosts = await prisma
  .$graphql(`
    query ($id: ID!) {
      user(id: $id) {
        posts { id title content published }
      }
    }
  `, 
  { id }
  )
```

</Code>

### Filtering for concrete values

TypeORM

```ts
const userRepository = getRepository(User)
const users = await userRepository.find({
  where: {
    name: "Alice"
  }
})
```

Prisma

```ts
const user = await prisma.users({
  where: {
    name: "Alice"
  }
})
```

### Other filter criteria

TypeORM

TypeORM doesn't expose other filter critera. But you can use the `QueryBuilder` API to send queries using `LIKE` and other SQL operators.

Prisma

Prisma generates many additional filters that are commonly used in modern application development:

- `<field>_ends_with` & `<field>_starts_with`
- `<field>_not_ends_with` & `<field>_not_starts_with`
- `<field>_gt` & `<field>_gte`
- `<field>_lt` & `<field>_lte`
- `<field>_contains` & `<field>_not_contains`
- `<field>_in` & `<field>_not_in`

### Relation filters

TypeORM

TypeORM doesn't offer a dedicated API for relation filters. You can get similar functionality by using the `QueryBuilder` or writing the queries by hand.

Prisma

Prisma lets you filter a list based on a criteria that applies not only to the models of the list being retrieved, but to a _relation_ of that model. 

For example, you want to fetch only those users that wrote a post with the title "Hello World". The filter criteria is therefore not referencing the user model, but the post model that's related to the user model:

```ts
query {
  user(where: {
    posts_some: {
      title: "Hello World"
    }
  }) {
    id
  }
}
```

### Pagination

TypeORM

```ts
const posts = await getRepository(Post).find({
  skip: 5,
  take: 10
})
```

Prisma

```ts
const posts = await prisma.posts({
  skip: 5,
  first: 10
})
```

In addition to `skip` and `first`, the Prisma API also offers:

- `last`
- `before` & `after` for cursor based pagination
- Relay-style pagination

## Writing data

### Creating objects

TypeORM ()

<Code languages={["Using `save`", "Using `create`", "Using `insert`"]}>


```ts
const user = new User()
user.name = "Alice"
user.email = "alice@prisma.io"
user.save()
```

```ts
const user = getRepository(User).create({
  name: "Alice",
  email: "alice@prisma.io"
})
user.save()
```

```ts
getRepository(User).insert({
  name: "Alice",
  email: "alice@prisma.io"
})
```

</Code>

Prisma

```ts
const user = new User({
  name: "Alice",
  email: "alice@prisma.io"
})
```

### Updating objects

TypeORM

```ts
const userRepository = getRepository(User)
const updatedUser = await userRepository.update(id, {
  name: "James",
  email: "james@prisma.io"
})
```

Prisma

```ts
const updatedUser = await prisma.updateUser({
  where: { id },
  data: {
    name: "James",
    email: "james@prisma.io"
  }
})
```

### Deleting objects

<Code languages={["Using `delete`", "Using `remove`"]}>

```ts
const userRepository = getRepository(User)
await userRepository.delete(id)
```

```ts
const userRepository = getRepository(User)
const deletedUser = await userRepository.remove(user)
```

</Code>

Prisma

```ts
const deletedUser = await prisma.deleteUser({ id })
```

### Batch updates

TypeORM

TypeORM doesn't offer a dedicated API for batch updates, but you can use `save` on an array of entities which leads to similar functionality.

Prisma

```ts
const updatedUsers = await prisma
  .updateManyUsers({
    data: {
      role: "ADMIN"
    },
    where: {
      email_ends_with: "@prisma.io"
    }
  })
```

### Batch deletes

<Code languages={["Using `delete`", "Using `remove`"]}>

```ts
const userRepository = getRepository(User)
await userRepository.delete([id1, id2, id3])
```

```ts
const userRepository = getRepository(User)
const deleteUsers = await userRepository
  .remove([user1, user2, user3])
```

</Code>

Prisma

```ts
await prisma.deleteManyUsers({
  id_in: [id1, id2, id3]
})
```

### Transactions

TypeORM

```ts
await getConnection().transaction(async transactionalEntityManager => {
    const user = getRepository(User).create({
      name: "Bob",
      email: "bob@prisma.io"
    })
    const post1 = getRepository(Post).create({
      title: "Join us for GraphQL Conf in 2019",
    })
    const post2 = getRepository(Post).create({
      title: "Subscribe to GraphQL Weekly for GraphQL news",
    })
    user.posts = [post1, post2]
    await transactionalEntityManager.save(post1)
    await transactionalEntityManager.save(post2)
    await transactionalEntityManager.save(user)
  })
```

Prisma

```ts
const newUser: User = await prisma.createUser({
  name: "Bob",
  email: "bob@prisma.io",
  posts: {
    create: [
      {
        title: "Join us for GraphQL Conf in 2019"
      },
      {
        title: "Subscribe to GraphQL Weekly for GraphQL news"
      }
    ]
  }
})
```
